﻿using System;
using System.Diagnostics;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BMLib;
using System.Xml;
using System.Threading;

namespace BrainMatch
{
    public delegate void CommandNon();
    public delegate void CommandString(string param);

    public partial class MainWindow : Form
    {
        private WaveManager m_Manager = null;
        private DataTable m_ResultTable = new DataTable();
        private List<WaveFileBar> m_Filebars = new List<WaveFileBar>();
        private string application_dir = Directory.GetCurrentDirectory();

        private bool closed = false;
        private DataRow lastRow = null;
        private string lastUserName="";
        private string lastFileName = "";
        public MainWindow()
        {
            InitializeComponent();
        }
        private void MakeResultTable()
        {
            m_ResultTable.Columns.Add(new DataColumn("类型",typeof(string)));
            m_ResultTable.Columns.Add(new DataColumn("左前", typeof(int)));
            m_ResultTable.Columns.Add(new DataColumn("左颞", typeof(int)));
            m_ResultTable.Columns.Add(new DataColumn("左后", typeof(int)));
            
            m_ResultTable.Columns.Add(new DataColumn("右前", typeof(int)));
            m_ResultTable.Columns.Add(new DataColumn("右颞", typeof(int)));
            m_ResultTable.Columns.Add(new DataColumn("右后", typeof(int)));
        }
        private void UpdateResultTable()
        {
            m_ResultTable.Rows.Clear();
            //创建质量列表
            List<DataRow> qlist = new List<DataRow>();
            foreach (var row in m_Manager.Dataset.label_quality)
            {
                DataRow qrow = m_ResultTable.NewRow();
                qrow["类型"] = row.name;
                qrow["左前"] = 0;
                qrow["左后"] = 0;
                qrow["左颞"] = 0;
                qrow["右前"] = 0;
                qrow["右颞"] = 0;
                qrow["右后"] = 0;
                qlist.Add(qrow);
            }

            foreach (WaveDataSet.label_namesRow name in m_Manager.Dataset.label_names)
            {
                
                string t = name.name.Split('_')[0];
                //string q = name.name.Split('_')[1];
                DataRow row = null;
                //DataRow qrow = null;
                //类型
                foreach (DataRow hw in m_ResultTable.Rows)
                {
                    if (hw["类型"].ToString() == t)
                    {
                        row = hw;
                        break;
                    }
                }
                
                if (row == null)
                {
                    row=m_ResultTable.NewRow();
                    row["类型"] = t;
                    row["左前"] = 0;
                    row["左后"] = 0;
                    row["左颞"] = 0;
                    row["右前"] = 0;
                    row["右颞"] = 0;
                    row["右后"] = 0;
                    m_ResultTable.Rows.Add(row);
                }

                //质量
                /*foreach (DataRow hw in qlist)
                {
                    if (hw["类型"].ToString() == q)
                    {
                        qrow = hw;
                        break;
                    }
                }
                if (qrow == null)
                {
                    qrow = m_ResultTable.NewRow();
                    qrow["类型"] = q;
                    qrow["左前"] = 0;
                    qrow["右前"] = 0;
                    qrow["左颞"] = 0;
                    qrow["右颞"] = 0;
                    qrow["左后"] = 0;
                    qrow["右后"] = 0;
                    qlist.Add(qrow);
                }*/

                foreach (WaveFileBar bar in flowLayoutPanel1.Controls)
                {
                    foreach (WaveBall ball in bar.Balls)
                    {
                        Debug.WriteLine(ball.Item.WaveName);
                        if (ball.Item.WaveType == t)
                        {
                            int v=(int)row[ball.Item.WaveName];
                            v++;
                            row[ball.Item.WaveName] = v;

                            //质量统计
                            foreach (var qrow in qlist)
                            {
                                string q = qrow["类型"].ToString();
                                if (ball.Item.Quality == q)
                                {
                                    int qv = (int)qrow[ball.Item.WaveName];
                                    qv++;
                                    qrow[ball.Item.WaveName] = qv;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            foreach (DataRow row in qlist)
            {
                m_ResultTable.Rows.Add(row);
            }
        }
        private void Clear()
        {
            m_Filebars.Clear();
            flowLayoutPanel1.Controls.Clear();
        }
        private void InsertWaveFile(string path)
        {
            
           // flowLayoutPanel1.Controls.Clear();

            WaveFileObject fo = new WaveFileObject();
            fo.LoadFile(path);

            m_Manager.MatchWaves(fo);

            WaveFileBar bar = new WaveFileBar(fo,m_Manager);
            flowLayoutPanel1.Controls.Add(bar);
            m_Filebars.Add(bar);
        }
        private void LoadNames()
        {
            flowLayoutPanel2.Controls.Clear();
            foreach (WaveDataSet.label_namesRow row in m_Manager.Dataset.label_names)
            {
                NameBall nb = new NameBall(row,m_Manager);
                flowLayoutPanel2.Controls.Add(nb);
            }
        }
        private void OnOpenFile(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                Clear();
                foreach(var file in openFileDialog1.FileNames)
                InsertWaveFile(file);
            }
        }

        private void MainWindow_Load(object sender, EventArgs e)
        {
            m_Manager = new WaveManager(this);
            MakeResultTable();
            dataGridView1.DataSource = m_ResultTable;
            UpdateResultTable();
            foreach (DataGridViewColumn c in dataGridView1.Columns)
                c.Width = 35;
            LoadNames();
            this.MouseWheel += new MouseEventHandler(MainWindow_MouseWheel);
            //InsertWaveFile(@"D:\Jobs\LabelForBrainWave\Source\TestData\8.dat1");

            Thread t = new Thread(new ThreadStart(MonitorThread));
            t.Start();
        }

        void MainWindow_MouseWheel(object sender, MouseEventArgs e)
        {
            int delta = 50;
            if (e.Delta > 0)
            {
                delta *= -1;
                if ((flowLayoutPanel1.VerticalScroll.Value + delta) > flowLayoutPanel1.VerticalScroll.Minimum)
                    flowLayoutPanel1.VerticalScroll.Value += delta;
                else
                    flowLayoutPanel1.VerticalScroll.Value = flowLayoutPanel1.VerticalScroll.Minimum;
            }
            else
            {
                if ((flowLayoutPanel1.VerticalScroll.Value + delta) < flowLayoutPanel1.VerticalScroll.Maximum)
                    flowLayoutPanel1.VerticalScroll.Value += delta;
                else
                    flowLayoutPanel1.VerticalScroll.Value = flowLayoutPanel1.VerticalScroll.Maximum;
                
            }

        }
        
        private void OnImportFiles(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                flowLayoutPanel1.Controls.Clear();
                m_Filebars.Clear();
                foreach (var item in openFileDialog1.FileNames)
                {
                    InsertWaveFile(item);
                }
                UpdateResultTable();
            }
        }

        private void OnNewName(object sender, EventArgs e)
        {
            NewFenleiDialog nf = new NewFenleiDialog();
            //if (nf.ShowDialog() == DialogResult.OK)
            //{
            //    foreach(string q in Properties.Settings.Default.Quality)
            //        m_Manager.InsertName(string.Format("{0}_{1}",nf.FenleiName,q), nf.FenleiColor, nf.FenleiRemark);
            //    //m_Manager.InsertName(string.Format("{0}_{1}", nf.FenleiName, "良"), nf.FenleiColor, nf.FenleiRemark);
            //    //m_Manager.InsertName(string.Format("{0}_{1}", nf.FenleiName, "差"), nf.FenleiColor, nf.FenleiRemark);
            //}
            LoadNames();
        }

        private void OnExitThe(object sender, EventArgs e)
        {
            Close();
        }

        private void OnDatabaseConfig(object sender, EventArgs e)
        {
            DatabaseConfigDialog dc = new DatabaseConfigDialog();
            dc.ShowDialog();
        }

        private void OnAbout(object sender, EventArgs e)
        {
            AboutDialog ad = new AboutDialog();
            ad.ShowDialog();
        }

        private void OnNamesEdit(object sender, EventArgs e)
        {
            //NamesManagerDialog nd = new NamesManagerDialog(m_Manager);
            LabelNamesEditor nd = new LabelNamesEditor(m_Manager);
            nd.ShowDialog();
            
            LoadNames();
        }

        private void OnOpenRAR(object sender, EventArgs e)
        {
            if (openFileDialog2.ShowDialog() == DialogResult.OK)
            {
                m_Filebars.Clear();
                flowLayoutPanel1.Controls.Clear();
                string rundir = application_dir;// Directory.GetCurrentDirectory();
                int n = openFileDialog2.FileName.LastIndexOf("\\")+1;
                int l=openFileDialog2.FileName.Length;
                string filename=openFileDialog2.FileName.Substring(n,l-n);

                ExecuteCommandSync(string.Format(@"del {0}\Data\*.dat",rundir));
                ExecuteCommandSync(string.Format(@"del  Data\{0}", filename));

                ExecuteCommandSync(string.Format(@"copy {0} {1}\Data",openFileDialog2.FileName,rundir));

                string filepath = string.Format(@"{0}\Data\{1}",rundir,filename);
                string outdir=string.Format(@"{0}\Data",rundir);
                string cmdstring=Properties.Settings.Default.rar.Replace("[file]",filepath);
                cmdstring=cmdstring.Replace("[outdir]",outdir);

                ExecuteCommandSync(cmdstring);//string.Format(@"{1}\Data\7z.exe e {1}\Data\{0} -o{1}\Data", filename,rundir));
                //MessageBox.Show(rundir);
                string datadir = string.Format(@"{0}\Data", rundir);
                string[] files=Directory.GetFiles(datadir,"*.dat");
                foreach (var file in files)
                {
                    InsertWaveFile(file);
                }
                UpdateResultTable();
            }
        }
        
        public void ExecuteCommandSync(object command)
        {
            try
            {
                // create the ProcessStartInfo using "cmd" as the program to be run,
                // and "/c " as the parameters.
                // Incidentally, /c tells cmd that we want it to execute the command that follows,
                // and then exit.
                System.Diagnostics.ProcessStartInfo procStartInfo =
                    new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);

                // The following commands are needed to redirect the standard output.
                // This means that it will be redirected to the Process.StandardOutput StreamReader.
                procStartInfo.RedirectStandardOutput = true;
                procStartInfo.UseShellExecute = false;
                // Do not create the black window.
                procStartInfo.CreateNoWindow = true;
                // Now we create a process, assign its ProcessStartInfo and start it
                System.Diagnostics.Process proc = new System.Diagnostics.Process();
                proc.StartInfo = procStartInfo;
                proc.Start();
                // Get the output into a string
                string result = proc.StandardOutput.ReadToEnd();
                // Display the command output.
                Console.WriteLine(result);
            }
            catch (Exception objException)
            {
                // Log the exception
            }
        }

        public void ReMatch()
        {
            foreach (WaveFileBar bar in flowLayoutPanel1.Controls)
                foreach (WaveBall ball in bar.Balls)
                {
                    m_Manager.MatchWave(ball.Item);
                    ball.UpdateType();
                }

            LoadNames();
            UpdateResultTable();
        }

        private void SaveFile(string file)
        {
            XmlDocument doc = new XmlDocument();
            XmlElement rootnode = doc.CreateElement("data_root");
            XmlElement testnode = doc.CreateElement("TestInfo");
            rootnode.AppendChild(testnode);

            string docname=string.Format("{0}_{1}_{2}",lastUserName,lastRow["UserName"],lastRow["Number"]);
            lastFileName = docname;

            testnode.SetAttribute("Name",docname);
            testnode.SetAttribute("UserName", lastRow["UserName"].ToString());
            testnode.SetAttribute("Sex", lastRow["Sex"].ToString());
            testnode.SetAttribute("BirthDate", lastRow["BirthDate"].ToString());
            testnode.SetAttribute("Handedness", lastRow["Handedness"].ToString());
            testnode.SetAttribute("EducationalBackground", lastRow["EducationalBackground"].ToString());
            testnode.SetAttribute("OccupationOrSpecialty", lastRow["OccupationOrSpecialty"].ToString());
            testnode.SetAttribute("EvaluationType", lastRow["EvaluationType"].ToString());
            testnode.SetAttribute("Memo", lastRow["Memo"].ToString());
            
            foreach (WaveFileBar bar in flowLayoutPanel1.Controls)
            {
                XmlElement bar_node = doc.CreateElement("wave_file");
                rootnode.AppendChild(bar_node);

                WaveFileObject fileobject = bar.WaveFile;
                bar_node.SetAttribute("FileName", fileobject.FileName);

                foreach (WaveBall ball in bar.Balls)
                {
                    WaveItem item = ball.Item;
                    XmlElement ball_node = doc.CreateElement("wave_node");
                    bar_node.AppendChild(ball_node);

                    ball_node.SetAttribute("Name", item.WaveName);
                    ball_node.SetAttribute("Type", item.WaveType);
                    ball_node.SetAttribute("Quality", item.Quality);

                    DataRow[] rs = m_Manager.Dataset.label_quality.Select(string.Format("id={0}", item.QualityID));
                    if (rs.Length > 0)
                    {
                        ball_node.SetAttribute("Quality_Value", rs[0]["value"].ToString());
                    }
                }
            }
            doc.AppendChild(rootnode);
            doc.Save(file);

            string export = Properties.Settings.Default.Exporter;//;
            if (export.IndexOf("\\") >= 0)
            {
                export = export.Replace("[file]", file);
                ExecuteCommandSync(export);
            }
            else
            {
                export = export.Replace("[file]", file);
                if (export.IndexOf('\"') >= 0)
                {
                    string tmpstr = export.Replace("\"","");

                    string run = string.Format("\"{0}\\{1}\"", application_dir, tmpstr);
                    //MessageBox.Show(run);
                    ExecuteCommandSync(run);
                }
                else
                {
                    //string run = string.Format("{0}\\{1}", application_dir, Properties.Settings.Default.Exporter);
                    ExecuteCommandSync(export);
                }
            }
           // MessageBox.Show("数据导出完成");
        }
        private void OnExportData(object sender, EventArgs e)
        {
            if(saveFileDialog1.ShowDialog()==DialogResult.OK)
            {
                SaveFile(saveFileDialog1.FileName);
            }
        }

        private string[] GetReportFiles(DataRow row, string username)
        {
            string dir = Properties.Settings.Default.ReportDirectory;
            string filter = string.Format("{0}_{1}_{2}*.egg", username, row["UserName"], row["Number"]);
            string[] files=Directory.GetFiles(dir,filter);
            return files;
        }
        private string[] GetDocFile(DataRow row,string username)
        {
            string dir = Properties.Settings.Default.DocDirectory;
            string filter = string.Format("{0}_{1}_{2}*.doc", username, row["UserName"], row["Number"]);
            
            string[] files = Directory.GetFiles(dir, filter);
            return files;
        }
        private void MonitorThread()
        {
            SqlConnection conn = new SqlConnection(Properties.Settings.Default.ReportDatabaseConnect);
            SqlDataAdapter adapter = new SqlDataAdapter("select * from report_queue where state=0",conn);
            SqlDataAdapter usradapter = new SqlDataAdapter("select * from users", conn);
            SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
            SqlCommandBuilder usrbuilder = new SqlCommandBuilder(usradapter);
            DataTable table = new DataTable("queue");
            DataTable usrtable = new DataTable("users");

            //adapter.Fill(table);
            //builder.GetUpdateCommand();


            while (!closed)
            {
                adapter.Fill(table);
                builder.GetUpdateCommand();

                usradapter.Fill(usrtable);
                usrbuilder.GetUpdateCommand();
                
                foreach (DataRow row in table.Rows)
                {
                    int state =(int) row["State"];

                    if(state!=0)continue;
                    string cusrp = null;
                    DataRow[] usrRow = usrtable.Select(string.Format("[id]={0}", row["UserID"]));
                    if (usrRow.Length > 0)
                    {
                        lastUserName = usrRow[0]["name"].ToString();
                        cusrp = usrRow[0]["report_cmd"].ToString();
                    }

                    string number = row["Number"].ToString();
                    string[] eggs = GetReportFiles(row,lastUserName);
                    lastRow = row;
                   
                    Invoke(new CommandNon(Clear),new object[]{});//清理

                    foreach (var egg in eggs)
                    {
                        FileInfo fi = new FileInfo(egg);

                        Invoke(new CommandString(InsertWaveFile), new object[] { egg });
                        
                        Thread.Sleep(1000);
                    }

                    string docname = string.Format("{0}_{1}_{2}", lastUserName, lastRow["UserName"], lastRow["Number"]);

                    string xmlfile = Properties.Settings.Default.OutTextDirectory + "\\" + docname + ".xml";
                    string txtfile = xmlfile.Replace("xml", "txt");
                    Invoke(new CommandString(SaveFile), new object[] { xmlfile });
                    string dsttxt = txtfile.Replace(Properties.Settings.Default.OutTextDirectory, Properties.Settings.Default.TxtDocDirectory);
                    File.Copy(txtfile, dsttxt, true);

                    bool cs = false;
                    if(cusrp!=null)
                    {
                        if (cusrp != "")
                        {
                            ExecuteCommandSync(cusrp);
                            cs = true;
                        }
                    }

                    if(!cs)
                        ExecuteCommandSync(Properties.Settings.Default.Reporter);

                    Thread.Sleep(1000);
                }
                
                
                
                //
                bool updated = false;
                usradapter.Fill(usrtable);
                usrbuilder.GetUpdateCommand();

                foreach (DataRow row in table.Rows)
                {
                    int s = (int)row["State"];
                    if (s == 1) continue;

                    string testtype = row["EvaluationType"].ToString();

                    DataRow[] usrRow = usrtable.Select(string.Format("[id]={0}", row["UserID"]));
                    if (usrRow.Length > 0)
                    {
                        lastUserName = usrRow[0]["name"].ToString();
                    }
                    string number = row["Number"].ToString();
                    string[] eggs = GetDocFile(row, lastUserName);
                    
                    if (eggs.Length > 0&&s==0)
                    {
                        row["State"] = 1;
                        if (usrRow.Length > 0)
                        {
                            decimal m = (decimal)usrRow[0]["Money"];
                            decimal p = 0;
                            if(testtype.IndexOf("普测")>=0)
                            {
                                p = (decimal)usrRow[0]["Prise"];
                                int ss = 1;
                                foreach (Char c in testtype)
                                    if (c == '&') ss++;
                                p *= ss;
                            }
                            
                            if(testtype=="精测")
                                p = (decimal)usrRow[0]["Prise2"];

                            m -= p;
                            usrRow[0]["Money"] = m;
                        }
                        updated = true;
                    }
                }

                if (updated)
                {
                    try
                    {
                        adapter.Update(table);
                        usradapter.Update(usrtable);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                    
                }

                Thread.Sleep(30000);
            }
        }
        private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            closed = true;
        }
    }
}